// areaview.cpp : Defines the game state that is where most gameplay will occur, in the 4-split screen
// adventure environment
//$Id: AreaView.cpp 28 2009-08-27 20:06:05Z brwarner2 $

#include "StdAfx.h"
#include "AreaView.h"
#include "ResourceManager.h"
#include "ObjectManager.h"
#include "ComponentManager.h"
#include "Messages.h"
#include "Components.h"
#include "Area.h"
#include "gmArea.h"
#include "SymbianEngine.h"
#include "Entity.h"

CAreaView::CAreaView(void) : IGameState()
{
	m_pGM = new gmMachine();
	gmBindStringLib(m_pGM);
	m_pComponents = new CComponentManager();
	RegisterComponents(m_pComponents);
	m_pObjects = new CObjectManager(m_pComponents, m_pGM);
	m_pObjects->RegisterGM();
	gmArea::RegisterLibrary(m_pGM);
}

void CAreaView::OnEnter( const std::string &prev )
{
	//Load each object in the gm directory
	WIN32_FIND_DATA ffd;
	HANDLE hFind = FindFirstFile("gm\\*.gm", &ffd);
	if(hFind != INVALID_HANDLE_VALUE)
	{
		//For each file
		do
		{
			//Load it in
			m_pObjects->LoadObjectData( std::string("gm\\") + ffd.cFileName );
		} while( FindNextFile(hFind, &ffd) != 0 );
	}

	//Load the players areas
	m_activeAreas[0] = m_activeAreas[1] = m_activeAreas[2] = m_activeAreas[3] = 0;

	//Create a global area table
	m_pAreaList = m_pGM->AllocTableObject();
	m_pGM->GetGlobals()->Set(m_pGM, "AreaList", gmVariable(m_pAreaList));

	//Load all the areas
	using boost::filesystem::directory_iterator;
	directory_iterator aiter = directory_iterator("areas\\");
	for(; aiter != directory_iterator(); aiter++)
	{
		if( boost::filesystem::extension(aiter->path()) != ".lvl" ) continue;
		CArea* pArea = new CArea(m_pObjects, m_pGM, this);
		LoadFromFile(aiter->path().string(), pArea);
		m_areas.push_back(pArea);

		//Add the area to the list
		m_pAreaList->Set(m_pGM, aiter->path().stem().c_str(), gmVariable(pArea->GetUser()));
	}

	//Create material for surfaces
	bug::render::Color c1 = bug::render::MakeColor(1.0f, 1.0f, 1.0f, 1.0f), c2 = bug::render::MakeColor(0.0f, 0.0f, 0.0f, 1.0f);
	bug::render::MaterialPointer mat = Resource()->GetTextureManager()->CreateMaterial(c1, c1, c1, c2, 1.0f);

	//Create render surfaces
	for( unsigned int i = 0; i < 4; i++)
	{
		m_targets[i] = Resource()->GetTextureManager()->CreateRenderTarget(400,300);
		m_targetSkins[i] = Resource()->GetTextureManager()->CreateSkin(mat, true);
		Resource()->GetTextureManager()->AddTexture(m_targetSkins[i], m_targets[i]);
	}

	//Register render targets
	for( unsigned int i = 0; i < 4; i++ )
		Resource()->GetEngine()->RegisterRenderTarget( m_targets[i], boost::bind(&CAreaView::RenderTarget, this, _1, i) );

	//Active screen
	m_nActiveScreen = 0;

	//Load needed skins
	m_inactive = Resource()->CreateTexture("screen_inactive.png");
	m_active = Resource()->CreateTexture("screen_active.png");

	//We're loaded
	m_pObjects->Broadcast(Messages::GameStart);
}

void CAreaView::Update( float fElapsed, float fTotal )
{
	//Check for TAB presses
	if(Resource()->GetInput()->IsReleased(bug::input::DEVICE_KEYBOARD, KEY_TAB)) m_nActiveScreen++;
	if( m_nActiveScreen > 3 ) m_nActiveScreen = 0;

	//Update the area
	for( unsigned int i = 0; i < 4; i++ )
	{
		if( m_activeAreas[i] == 0 ) continue;
		bool bUpdate = true;
		if( i > 0 )
			for( int j = i-1; j >= 0; j-- )
				if( m_activeAreas[i] == m_activeAreas[j] ) bUpdate = false;
		if( bUpdate )
			m_activeAreas[i]->Update(fElapsed, fTotal);
	}
}

void CAreaView::SetPlayerArea(unsigned int player, CArea* pArea)
{
	m_activeAreas[player] = pArea;
}

void CAreaView::Render( void )
{
	//Get rendering sprite
	bug::render::CSprite* pSprite = Resource()->GetSprite();

	//Draw 2D
	pSprite->Begin2D();

	//Render the areas
	for( unsigned int i = 0; i < 4; i++ ) {
		switch(i)
		{
		case 0:
			pSprite->Draw( m_targetSkins[i], 0, 0, 400, 300 );
			break;
		case 1:
			pSprite->Draw( m_targetSkins[i], 400, 0, 400, 300 );
			break;
		case 2:
			pSprite->Draw( m_targetSkins[i], 0, 300, 400, 300 );
			break;
		case 3:
			pSprite->Draw( m_targetSkins[i], 400, 300, 400, 300 );
			break;
		}
	}

	//End 2D
	pSprite->End2D();
}

void CAreaView::RenderTarget( bug::render::IRenderDevice*, unsigned int area )
{
	if( m_activeAreas[area] == 0 ) return;

	//Get rendering sprite
	bug::render::CSprite* pSprite = Resource()->GetSprite();

	//Draw 2D
	pSprite->Begin2D();

	//Get the player in the area
	do
	{
		ObjectID player = m_activeAreas[area]->GetByName(std::string("player") + boost::lexical_cast<std::string>(area));
		if( player == -1 ) break;
		CEntity* pEnt = dynamic_cast<CEntity*>(m_pObjects->GetComponent(player, CEntity::COMPONENT_ID));
		bug::math::CVector pos = pEnt->Position()*-1.0f + bug::math::CVector( 200, 0, 150 );
		pos.m_y = pos.m_z; pos.m_z = 0.0f;

		//Offset drawing
		pSprite->RegisterOffset( pos );

		//Render the area
		m_activeAreas[area]->Render();

		pSprite->PopOffset();
	}while(false);

	//Render the border
	if( area == m_nActiveScreen )
		pSprite->Draw( m_active, 0, 0, 400, 300 );
	else
		pSprite->Draw( m_inactive, 0, 0, 400, 300 );

	//End 2D
	pSprite->End2D();
}

CAreaView::~CAreaView(void)
{
	std::vector<CArea*>::iterator iter = m_areas.begin();
	for(; iter != m_areas.end(); iter++)
	{
		delete (*iter);
	}
	m_areas.clear();
	SecureZeroMemory(m_activeAreas, sizeof(CArea*)*4);
	delete m_pObjects;
	delete m_pComponents;
	delete m_pGM;
	m_pGM = 0;
	m_pComponents = 0;
	m_pObjects = 0;
}
